bitkeeper revision 1.1546 (42944efdY94XWSK3i6H669MdigOOzw)
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Wed, 25 May 2005 10:10:05 +0000 (10:10 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Wed, 25 May 2005 10:10:05 +0000 (10:10 +0000)
XendDomain.py:
  Move save/restore code in seperate file.
XendCheckpoint.py:
  Support code for save/restore of domains.
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
.rootkeys
tools/python/xen/xend/XendCheckpoint.py [new file with mode: 0644]
tools/python/xen/xend/XendDomain.py

index 517e6ebce0d5263760e56663b119fca7dc55f198..17ee3a6b3cc7c70b89a16dadbb5b3ec9858dee94 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/python/xen/xend/PrettyPrint.py
 40e15b7eeQxWE_hUPB2YTgM9fsZ1PQ tools/python/xen/xend/Vifctl.py
 4270cc81xbweGYhsM4326N3dX1bGHQ tools/python/xen/xend/XendBootloader.py
+42944ee8FQaAdZMF56O_WkWyBdCalA tools/python/xen/xend/XendCheckpoint.py
 40c9c4688m3eqnC8fhLu1APm36VOVA tools/python/xen/xend/XendClient.py
 40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/python/xen/xend/XendConsole.py
 40c9c468WnXs6eOUSff23IIGI4kMfQ tools/python/xen/xend/XendDB.py
diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py
new file mode 100644 (file)
index 0000000..46a1936
--- /dev/null
@@ -0,0 +1,143 @@
+# Copyright (C) 2005 Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
+
+# This file is subject to the terms and conditions of the GNU General
+# Public License.  See the file "COPYING" in the main directory of
+# this archive for more details.
+
+import errno
+import os
+import select
+import sxp
+from string import join
+from struct import pack, unpack, calcsize
+from xen.util.xpopen import xPopen3
+import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
+
+from XendLogging import log
+
+SIGNATURE = "LinuxGuestRecord"
+PAGE_SIZE = 4096
+PATH_XC_SAVE = "/usr/libexec/xen/xc_save"
+PATH_XC_RESTORE = "/usr/libexec/xen/xc_restore"
+
+sizeof_int = calcsize("i")
+sizeof_unsigned_long = calcsize("L")
+
+def save(xd, fd, dominfo):
+    if os.write(fd, SIGNATURE) != len(SIGNATURE):
+        raise XendError("could not write guest state file: signature")
+
+    config = sxp.to_string(dominfo.sxpr())
+    if os.write(fd, pack("!i", len(config))) != sizeof_int:
+        raise XendError("could not write guest state file: config len")
+    if os.write(fd, config) != len(config):
+        raise XendError("could not write guest state file: config")
+
+    cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd),
+           dominfo.id]
+    log.info("[xc_save] " + join(cmd))
+    child = xPopen3(cmd, True, -1, [fd, xc.handle()])
+    
+    lasterr = ""
+    p = select.poll()
+    p.register(child.fromchild.fileno())
+    p.register(child.childerr.fileno())
+    while True:
+        r = p.poll()
+        for (fd, event) in r:
+            if not event & select.POLLIN:
+                continue
+            if fd == child.childerr.fileno():
+                l = child.childerr.readline()
+                log.error(l.rstrip())
+                lasterr = l.rstrip()
+            if fd == child.fromchild.fileno():
+                l = child.fromchild.readline()
+                if l.rstrip() == "suspend":
+                    log.info("suspending %s" % dominfo.id)
+                    xd.domain_shutdown(dominfo.id, reason='suspend')
+                    dominfo.state_wait("suspended")
+                    log.info("suspend %s done" % dominfo.id)
+                    child.tochild.write("done\n")
+                    child.tochild.flush()
+        if filter(lambda (fd, event): event & select.POLLHUP, r):
+            break
+
+    if child.wait() >> 8 == 127:
+        lasterr = "popen %s failed" % PATH_XC_SAVE
+    if child.wait() != 0:
+        raise XendError("xc_save failed: %s" % lasterr)
+
+    xd.domain_destroy(dominfo.id)
+    return None
+
+def restore(xd, fd):
+    try:
+        signature = fd.read_exact(len(SIGNATURE),
+            "not a valid guest state file: signature read")
+        if signature != SIGNATURE:
+            raise XendError("not a valid guest state file: found '%s'" %
+                            signature)
+    
+        l = fd.read_exact(sizeof_int,
+                          "not a valid guest state file: config size read")
+        vmconfig_size = unpack("!i", l)[0]
+        vmconfig_buf = fd.read_exact(vmconfig_size,
+            "not a valid guest state file: config read")
+    
+        p = sxp.Parser()
+        p.input(vmconfig_buf)
+        if not p.ready:
+            raise XendError("not a valid guest state file: config parse")
+    
+        vmconfig = p.get_val()
+        dominfo = xd.domain_configure(vmconfig)
+    
+        l = fd.read_exact(sizeof_unsigned_long,
+                          "not a valid guest state file: pfn count read")
+        nr_pfns = unpack("=L", l)[0]   # XXX endianess
+        if nr_pfns > 1024*1024:     # XXX
+            raise XendError(
+                "not a valid guest state file: pfn count out of range")
+    
+        # XXXcl hack: fd.tell will sync up the object and
+        #             underlying file descriptor
+        ignore = fd.tell()
+    
+        cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd.fileno()),
+               dominfo.id, str(nr_pfns)]
+        log.info("[xc_restore] " + join(cmd))
+        child = xPopen3(cmd, True, -1, [fd.fileno(), xc.handle()])
+        child.tochild.close()
+    
+        lasterr = ""
+        p = select.poll()
+        p.register(child.fromchild.fileno())
+        p.register(child.childerr.fileno())
+        while True:
+            r = p.poll()
+            for (fd, event) in r:
+                if not event & select.POLLIN:
+                    continue
+                if fd == child.childerr.fileno():
+                    l = child.childerr.readline()
+                    log.error(l.rstrip())
+                    lasterr = l.rstrip()
+                if fd == child.fromchild.fileno():
+                    l = child.fromchild.readline()
+                    log.info(l.rstrip())
+            if filter(lambda (fd, event): event & select.POLLHUP, r):
+                break
+    
+        if child.wait() >> 8 == 127:
+            lasterr = "popen %s failed" % PATH_XC_RESTORE
+        if child.wait() != 0:
+            raise XendError("xc_restore failed: %s" % lasterr)
+    
+        return dominfo
+
+    except IOError, ex:
+        if ex.errno == errno.ENOENT:
+            raise XendError("can't open guest state file %s" % src)
+        else:
+            raise
index 87cf57992cff22f0d8fb1c8dd877f2d257f2b07b..01df63ef2c8fbde90128e55134b5869cf09a34c3 100644 (file)
@@ -5,6 +5,8 @@
  Nothing here is persistent (across reboots).
  Needs to be persistent for one uptime.
 """
+import os
+import scheduler
 import sys
 import traceback
 import time
@@ -13,6 +15,7 @@ import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
 
 import sxp
 import XendRoot; xroot = XendRoot.instance()
+import XendCheckpoint
 import XendDB
 import XendDomainInfo
 import XendMigrate
@@ -20,18 +23,8 @@ import EventServer; eserver = EventServer.instance()
 from XendError import XendError
 from XendLogging import log
 
-import scheduler
-
 from xen.xend.server import channel
 
-
-import errno
-import os
-import select
-from string import join
-from struct import pack, unpack, calcsize
-from xen.util.xpopen import xPopen3
-
 __all__ = [ "XendDomain" ]
 
 SHUTDOWN_TIMEOUT = 30
@@ -330,91 +323,17 @@ class XendDomain:
         @param progress: output progress if true
         """
 
-        SIGNATURE = "LinuxGuestRecord"
-        sizeof_int = calcsize("i")
-        sizeof_unsigned_long = calcsize("L")
-        PAGE_SIZE = 4096
-        PATH_XC_RESTORE = "/usr/libexec/xen/xc_restore"
-
         class XendFile(file):
             def read_exact(self, size, error_msg):
                 buf = self.read(size)
                 if len(buf) != size:
                     raise XendError(error_msg)
                 return buf
-        
-        try:
-            fd = XendFile(src, 'rb')
-
-            signature = fd.read_exact(len(SIGNATURE),
-                "not a valid guest state file: signature read")
-            if signature != SIGNATURE:
-                raise XendError("not a valid guest state file: found '%s'" %
-                                signature)
-
-            l = fd.read_exact(sizeof_int,
-                              "not a valid guest state file: config size read")
-            vmconfig_size = unpack("!i", l)[0]
-            vmconfig_buf = fd.read_exact(vmconfig_size,
-                "not a valid guest state file: config read")
-
-            p = sxp.Parser()
-            p.input(vmconfig_buf)
-            if not p.ready:
-                raise XendError("not a valid guest state file: config parse")
-
-            vmconfig = p.get_val()
-            dominfo = self.domain_configure(vmconfig)
-
-            l = fd.read_exact(sizeof_unsigned_long,
-                              "not a valid guest state file: pfn count read")
-            nr_pfns = unpack("=L", l)[0]   # XXX endianess
-            if nr_pfns > 1024*1024:     # XXX
-                raise XendError(
-                    "not a valid guest state file: pfn count out of range")
-
-            # XXXcl hack: fd.tell will sync up the object and
-            #             underlying file descriptor
-            ignore = fd.tell()
-
-            cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd.fileno()),
-                   dominfo.id, str(nr_pfns)]
-            log.info("[xc_restore] " + join(cmd))
-            child = xPopen3(cmd, True, -1, [fd.fileno(), xc.handle()])
-            child.tochild.close()
-
-            lasterr = ""
-            p = select.poll()
-            p.register(child.fromchild.fileno())
-            p.register(child.childerr.fileno())
-            while True:
-                r = p.poll()
-                for (fd, event) in r:
-                    if not event & select.POLLIN:
-                        continue
-                    if fd == child.childerr.fileno():
-                        l = child.childerr.readline()
-                        log.error(l.rstrip())
-                        lasterr = l.rstrip()
-                    if fd == child.fromchild.fileno():
-                        l = child.fromchild.readline()
-                        log.info(l.rstrip())
-                if filter(lambda (fd, event): event & select.POLLHUP, r):
-                    break
-
-            if child.wait() >> 8 == 127:
-                lasterr = "popen %s failed" % PATH_XC_RESTORE
-            if child.wait() != 0:
-                raise XendError("xc_restore failed: %s" % lasterr)
 
-            return dominfo
+        fd = XendFile(src, 'rb')
+
+        return XendCheckpoint.restore(self, fd)
 
-        except IOError, ex:
-            if ex.errno == errno.ENOENT:
-                raise XendError("can't open guest state file %s" % src)
-            else:
-                raise
-    
     def domain_get(self, id):
         """Get up-to-date info about a domain.
 
@@ -604,61 +523,12 @@ class XendDomain:
         @param progress: output progress if true
         """
 
-        SIGNATURE = "LinuxGuestRecord"
-        sizeof_int = calcsize("i")
-        PATH_XC_SAVE = "/usr/libexec/xen/xc_save"
-
         try:
             dominfo = self.domain_lookup(id)
 
             fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
 
-            if os.write(fd, SIGNATURE) != len(SIGNATURE):
-                raise XendError("could not write guest state file: signature")
-
-            config = sxp.to_string(dominfo.sxpr())
-            if os.write(fd, pack("!i", len(config))) != sizeof_int:
-                raise XendError("could not write guest state file: config len")
-            if os.write(fd, config) != len(config):
-                raise XendError("could not write guest state file: config")
-
-            cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd),
-                   dominfo.id]
-            log.info("[xc_save] " + join(cmd))
-            child = xPopen3(cmd, True, -1, [fd, xc.handle()])
-            
-            lasterr = ""
-            p = select.poll()
-            p.register(child.fromchild.fileno())
-            p.register(child.childerr.fileno())
-            while True:
-                r = p.poll()
-                for (fd, event) in r:
-                    if not event & select.POLLIN:
-                        continue
-                    if fd == child.childerr.fileno():
-                        l = child.childerr.readline()
-                        log.error(l.rstrip())
-                        lasterr = l.rstrip()
-                    if fd == child.fromchild.fileno():
-                        l = child.fromchild.readline()
-                        if l.rstrip() == "suspend":
-                            log.info("suspending %s" % dominfo.id)
-                            self.domain_shutdown(dominfo.id, reason='suspend')
-                            dominfo.state_wait("suspended")
-                            log.info("suspend %s done" % dominfo.id)
-                            child.tochild.write("done\n")
-                            child.tochild.flush()
-                if filter(lambda (fd, event): event & select.POLLHUP, r):
-                    break
-
-            if child.wait() >> 8 == 127:
-                lasterr = "popen %s failed" % PATH_XC_SAVE
-            if child.wait() != 0:
-                raise XendError("xc_save failed: %s" % lasterr)
-
-            self.domain_destroy(dominfo.id)
-            return None
+            return XendCheckpoint.save(self, fd, dominfo)
 
         except:
             raise